"""
AI服务集成
处理LangChain和DeepSeek API的集成，提供AI内容生成功能。
"""

import os
import logging
import asyncio
from typing import Dict, List, Optional, Any
from datetime import datetime
import json

from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
from langchain.callbacks.base import BaseCallbackHandler
import httpx

from ..utils.retry_handler import retry_on_failure, RetryableError, NonRetryableError

logger = logging.getLogger(__name__)


class DeepSeekCallbackHandler(BaseCallbackHandler):
    """DeepSeek API调用的回调处理器"""
    
    def __init__(self, session_id: str = None):
        self.session_id = session_id
        self.start_time = None
        self.tokens_used = 0
    
    def on_llm_start(self, serialized: Dict[str, Any], prompts: List[str], **kwargs) -> None:
        """LLM开始调用时的回调"""
        self.start_time = datetime.now()
        logger.info(f"开始AI调用 - 会话ID: {self.session_id}")
    
    def on_llm_end(self, response, **kwargs) -> None:
        """LLM调用结束时的回调"""
        if self.start_time:
            duration = (datetime.now() - self.start_time).total_seconds()
            logger.info(f"AI调用完成 - 会话ID: {self.session_id}, 耗时: {duration:.2f}秒")


class AIService:
    """
    AI服务类
    
    负责与DeepSeek API集成，提供PPT内容生成功能
    """
    
    def __init__(self):
        """初始化AI服务"""
        self.api_key = os.getenv("DEEPSEEK_API_KEY")
        self.base_url = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com")
        self.model_name = os.getenv("DEEPSEEK_MODEL", "deepseek-chat")
        self.max_retries = int(os.getenv("AI_MAX_RETRIES", "3"))
        self.timeout = int(os.getenv("AI_TIMEOUT", "60"))
        
        if not self.api_key:
            logger.warning("未设置DEEPSEEK_API_KEY环境变量")
        
        # 初始化LangChain客户端
        self._init_langchain_client()
    
    def _init_langchain_client(self):
        """初始化LangChain客户端"""
        try:
            self.llm = ChatOpenAI(
                model=self.model_name,
                openai_api_key=self.api_key,
                openai_api_base=self.base_url,
                temperature=0.7,
                max_tokens=4000,
                timeout=self.timeout,
                max_retries=self.max_retries
            )
            logger.info("LangChain客户端初始化成功")
        except Exception as e:
            logger.error(f"LangChain客户端初始化失败: {e}")
            self.llm = None
    
    @retry_on_failure(max_retries=2, base_delay=1.0, operation_name="test_connection")
    async def test_connection(self) -> Dict[str, Any]:
        """
        测试与DeepSeek API的连接
        
        Returns:
            Dict: 连接测试结果
        """
        if not self.llm:
            return {
                "success": False,
                "error": "LangChain客户端未初始化",
                "details": "请检查API密钥和配置"
            }
        
        try:
            # 发送简单的测试消息
            test_message = [
                SystemMessage(content="你是一个AI助手。"),
                HumanMessage(content="请回复'连接测试成功'")
            ]
            
            callback = DeepSeekCallbackHandler("test_connection")
            response = await asyncio.to_thread(
                self.llm.invoke,
                test_message,
                callbacks=[callback]
            )
            
            return {
                "success": True,
                "message": "DeepSeek API连接成功",
                "response": response.content,
                "model": self.model_name
            }
            
        except Exception as e:
            logger.error(f"DeepSeek API连接测试失败: {e}")
            return {
                "success": False,
                "error": str(e),
                "details": "API连接失败，请检查网络和API密钥"
            }
    
    @retry_on_failure(max_retries=3, base_delay=2.0, operation_name="generate_presentation_outline")
    async def generate_presentation_outline(
        self, 
        topic: str, 
        requirements: Optional[str] = None,
        slide_count: int = 10,
        session_id: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        生成演示文稿大纲
        
        Args:
            topic: 演示文稿主题
            requirements: 额外要求
            slide_count: 幻灯片数量
            session_id: 会话ID
            
        Returns:
            Dict: 生成的大纲结果
        """
        if not self.llm:
            return {
                "success": False,
                "error": "AI服务未初始化"
            }
        
        try:
            # 构建提示词
            system_prompt = """你是一个专业的演示文稿内容生成专家。请根据用户提供的主题和要求，生成一个结构化的演示文稿大纲。

要求：
1. 生成的大纲应该逻辑清晰，层次分明
2. 每个幻灯片都应该有明确的标题和主要内容点
3. 内容应该专业、准确、有价值
4. 适合商务或学术演示场景
5. 返回JSON格式的结构化数据

返回格式示例：
{
  "title": "演示文稿标题",
  "slides": [
    {
      "slide_number": 1,
      "title": "幻灯片标题",
      "type": "title",
      "content": ["主要内容点1", "主要内容点2"],
      "notes": "演讲者备注"
    }
  ]
}"""
            
            user_prompt = f"""请为以下主题生成一个包含{slide_count}张幻灯片的演示文稿大纲：

主题：{topic}

{f"额外要求：{requirements}" if requirements else ""}

请确保：
1. 第一张幻灯片是标题页
2. 最后一张幻灯片是总结或结论
3. 中间的幻灯片按逻辑顺序组织内容
4. 每张幻灯片的内容点不超过5个
5. 返回标准的JSON格式"""
            
            messages = [
                SystemMessage(content=system_prompt),
                HumanMessage(content=user_prompt)
            ]
            
            callback = DeepSeekCallbackHandler(session_id)
            response = await asyncio.to_thread(
                self.llm.invoke,
                messages,
                callbacks=[callback]
            )
            
            # 解析响应
            try:
                outline_data = json.loads(response.content)
                return {
                    "success": True,
                    "outline": outline_data,
                    "message": "演示文稿大纲生成成功"
                }
            except json.JSONDecodeError:
                # 如果JSON解析失败，尝试提取内容
                return {
                    "success": False,
                    "error": "AI返回的内容格式不正确",
                    "raw_response": response.content
                }
                
        except Exception as e:
            logger.error(f"生成演示文稿大纲失败: {e}")
            return {
                "success": False,
                "error": str(e)
            }
    
    @retry_on_failure(max_retries=3, base_delay=1.5, operation_name="generate_slide_content")
    async def generate_slide_content(
        self,
        slide_title: str,
        slide_context: str,
        slide_type: str = "content",
        session_id: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        生成单个幻灯片的详细内容
        
        Args:
            slide_title: 幻灯片标题
            slide_context: 幻灯片上下文信息
            slide_type: 幻灯片类型
            session_id: 会话ID
            
        Returns:
            Dict: 生成的幻灯片内容
        """
        if not self.llm:
            return {
                "success": False,
                "error": "AI服务未初始化"
            }
        
        try:
            system_prompt = """你是一个专业的演示文稿内容创作专家。请根据提供的幻灯片标题和上下文，生成详细的幻灯片内容。

要求：
1. 内容应该简洁明了，适合演示展示
2. 每个要点都应该有价值和意义
3. 语言专业但易于理解
4. 提供合适的视觉元素建议
5. 包含演讲者备注

返回JSON格式：
{
  "title": "幻灯片标题",
  "content": ["内容要点1", "内容要点2", "内容要点3"],
  "visual_elements": ["视觉元素建议1", "视觉元素建议2"],
  "notes": "演讲者备注"
}"""
            
            user_prompt = f"""请为以下幻灯片生成详细内容：

标题：{slide_title}
类型：{slide_type}
上下文：{slide_context}

请生成：
1. 3-5个主要内容要点
2. 2-3个视觉元素建议（图表、图片、图标等）
3. 简洁的演讲者备注

返回标准JSON格式。"""
            
            messages = [
                SystemMessage(content=system_prompt),
                HumanMessage(content=user_prompt)
            ]
            
            callback = DeepSeekCallbackHandler(session_id)
            response = await asyncio.to_thread(
                self.llm.invoke,
                messages,
                callbacks=[callback]
            )
            
            # 解析响应
            try:
                slide_data = json.loads(response.content)
                return {
                    "success": True,
                    "slide": slide_data,
                    "message": "幻灯片内容生成成功"
                }
            except json.JSONDecodeError:
                return {
                    "success": False,
                    "error": "AI返回的内容格式不正确",
                    "raw_response": response.content
                }
                
        except Exception as e:
            logger.error(f"生成幻灯片内容失败: {e}")
            return {
                "success": False,
                "error": str(e)
            }
    
    @retry_on_failure(max_retries=2, base_delay=1.0, operation_name="optimize_content")
    async def optimize_content(
        self,
        content: str,
        optimization_type: str = "clarity",
        session_id: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        优化内容
        
        Args:
            content: 要优化的内容
            optimization_type: 优化类型 (clarity, conciseness, engagement)
            session_id: 会话ID
            
        Returns:
            Dict: 优化后的内容
        """
        if not self.llm:
            return {
                "success": False,
                "error": "AI服务未初始化"
            }
        
        optimization_prompts = {
            "clarity": "请优化以下内容，使其更加清晰易懂",
            "conciseness": "请优化以下内容，使其更加简洁有力",
            "engagement": "请优化以下内容，使其更加吸引人和有趣"
        }
        
        try:
            system_prompt = f"""你是一个专业的内容编辑专家。{optimization_prompts.get(optimization_type, optimization_prompts['clarity'])}。

要求：
1. 保持原意不变
2. 提高内容质量
3. 适合演示文稿展示
4. 返回优化后的内容"""
            
            user_prompt = f"请优化以下内容：\n\n{content}"
            
            messages = [
                SystemMessage(content=system_prompt),
                HumanMessage(content=user_prompt)
            ]
            
            callback = DeepSeekCallbackHandler(session_id)
            response = await asyncio.to_thread(
                self.llm.invoke,
                messages,
                callbacks=[callback]
            )
            
            return {
                "success": True,
                "optimized_content": response.content,
                "original_content": content,
                "optimization_type": optimization_type
            }
            
        except Exception as e:
            logger.error(f"内容优化失败: {e}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def get_service_status(self) -> Dict[str, Any]:
        """
        获取AI服务状态
        
        Returns:
            Dict: 服务状态信息
        """
        return {
            "service_name": "AI内容生成服务",
            "model": self.model_name,
            "base_url": self.base_url,
            "api_key_configured": bool(self.api_key),
            "client_initialized": self.llm is not None,
            "max_retries": self.max_retries,
            "timeout": self.timeout
        }


# 全局AI服务实例
ai_service = AIService()